package org.checkboo.hopefullyengine.boundingvolumes;

import java.nio.FloatBuffer;

import org.checkboo.math.FloatMath;
import org.checkboo.math.Matrix44f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

public class Frustum {

	private float[][] planes;
	
	public Frustum(){
		planes = new float[6][4];
	}
	
	public float[][] getPlanes() {
		FloatBuffer proj = BufferUtils.createFloatBuffer(16);
    	FloatBuffer modl = BufferUtils.createFloatBuffer(16);
    	
    	GL11.glGetFloat( GL11.GL_PROJECTION_MATRIX, proj );
    	Matrix44f projM = new Matrix44f();
    	projM.fromFloatBuffer(proj);

    	GL11.glGetFloat( GL11.GL_MODELVIEW_MATRIX, modl );
    	Matrix44f modlM = new Matrix44f();
    	modlM.fromFloatBuffer(modl);
   	
    	modlM.multiply(projM); 
    	getPlanes(modlM);
		return planes;
	}

	public void setPlanes(float[][] planes) {
		this.planes = planes;
	}

	public void getPlanes(Matrix44f matrix) {
		float divider;
		
		this.planes[0][0] = matrix.getV14() - matrix.getV11();
		this.planes[0][1] = matrix.getV24() - matrix.getV21();
		this.planes[0][2] = matrix.getV34() - matrix.getV31();
		this.planes[0][3] = matrix.getV44() - matrix.getV41();
		
		divider = FloatMath.sqrt(FloatMath.sqr(this.planes[0][0]) + FloatMath.sqr(this.planes[0][1]) + FloatMath.sqr(this.planes[0][2]));
		
		this.planes[0][0] /= divider;
		this.planes[0][1] /= divider;
		this.planes[0][2] /= divider;
		this.planes[0][3] /= divider;
		
		this.planes[1][0] = matrix.getV14() + matrix.getV11();
		this.planes[1][1] = matrix.getV24() + matrix.getV21();
		this.planes[1][2] = matrix.getV34() + matrix.getV31();
		this.planes[1][3] = matrix.getV44() + matrix.getV41();
		
		divider = FloatMath.sqrt(FloatMath.sqr(this.planes[1][0]) + FloatMath.sqr(this.planes[1][1]) + FloatMath.sqr(this.planes[1][2]));
		
		this.planes[1][0] /= divider;
		this.planes[1][1] /= divider;
		this.planes[1][2] /= divider;
		this.planes[1][3] /= divider;
		
		this.planes[2][0] = matrix.getV14() + matrix.getV12();
		this.planes[2][1] = matrix.getV24() + matrix.getV22();
		this.planes[2][2] = matrix.getV34() + matrix.getV32();
		this.planes[2][3] = matrix.getV44() + matrix.getV42();
		
		divider = FloatMath.sqrt(FloatMath.sqr(this.planes[2][0]) + FloatMath.sqr(this.planes[2][1]) + FloatMath.sqr(this.planes[2][2]));
		
		this.planes[2][0] /= divider;
		this.planes[2][1] /= divider;
		this.planes[2][2] /= divider;
		this.planes[2][3] /= divider;
		
		this.planes[3][0] = matrix.getV14() - matrix.getV12();
		this.planes[3][1] = matrix.getV24() - matrix.getV22();
		this.planes[3][2] = matrix.getV34() - matrix.getV32();
		this.planes[3][3] = matrix.getV44() - matrix.getV42();
		
		divider = FloatMath.sqrt(FloatMath.sqr(this.planes[3][0]) + FloatMath.sqr(this.planes[3][1]) + FloatMath.sqr(this.planes[3][2]));
		
		this.planes[3][0] /= divider;
		this.planes[3][1] /= divider;
		this.planes[3][2] /= divider;
		this.planes[3][3] /= divider;
		
		this.planes[4][0] = matrix.getV14() - matrix.getV13();
		this.planes[4][1] = matrix.getV24() - matrix.getV23();
		this.planes[4][2] = matrix.getV34() - matrix.getV33();
		this.planes[4][3] = matrix.getV44() - matrix.getV43();
		
		divider = FloatMath.sqrt(FloatMath.sqr(this.planes[4][0]) + FloatMath.sqr(this.planes[4][1]) + FloatMath.sqr(this.planes[4][2]));
		
		this.planes[4][0] /= divider;
		this.planes[4][1] /= divider;
		this.planes[4][2] /= divider;
		this.planes[4][3] /= divider;
		
		this.planes[5][0] = matrix.getV14() + matrix.getV13();
		this.planes[5][1] = matrix.getV24() + matrix.getV23();
		this.planes[5][2] = matrix.getV34() + matrix.getV33();
		this.planes[5][3] = matrix.getV44() + matrix.getV43();
		
		divider = FloatMath.sqrt(FloatMath.sqr(this.planes[5][0]) + FloatMath.sqr(this.planes[5][1]) + FloatMath.sqr(this.planes[5][2]));
		
		this.planes[5][0] /= divider;
		this.planes[5][1] /= divider;
		this.planes[5][2] /= divider;
		this.planes[5][3] /= divider;
	}
}
